import copy
from typing import Callable

from python_part.main_policy_database_member.ProtectingEntities import ProtectingEntities
from python_part.main_policy_database_member.ReadWriteClass import ReadWriteClass
from python_part.main_policy_database_member.struct_for_connect import *
import ctypes as ct

from GlobaLogger import Log
log = Log(__name__).getlog()

class BPFBackend:
    def __init__(self,
                 bpf_obj,
                 get_all_policy: Callable[[], tuple[dict, dict, dict]],
                 update_entity_path_to_rwclass_id: Callable[[str, int], None],
                 update_rwclass_id_to_rwclass: Callable[[int, ReadWriteClass], None],
                 delete_entity_path_to_rwclass_id: Callable[[str], None],
                 delete_rwclass_id_to_rwclass: Callable[[int], None]):
        self.__bpf_obj = bpf_obj
        self.__bpf_obj["log_output"].open_ring_buffer(self.__handle_log_output)
        self.__bpf_obj["class_modify_event_sender"].open_ring_buffer(self.__handle_class_modify_event)
        self.__bpf_obj["class_new_event_sender"].open_ring_buffer(self.__handle_class_new_event)
        self.__bpf_obj["class_delete_event_sender"].open_ring_buffer(self.__handle_class_delete_event)

        self.update_entity_path_to_rwclass_id = update_entity_path_to_rwclass_id
        self.update_rwclass_id_to_rwclass = update_rwclass_id_to_rwclass
        self.delete_entity_path_to_rwclass_id = delete_entity_path_to_rwclass_id
        self.delete_rwclass_id_to_rwclass = delete_rwclass_id_to_rwclass
        self.get_all_policy = get_all_policy

        self.log_num = 0

    def __handle_log_output(self, cpu, data, size):
        data = self.__bpf_obj["log_output"].event(data)
        log.info(f"收到 eBPF 日志 -> {self.log_num}、log_id:{data.message_id}, log_message:{data.message}")
        self.log_num += 1

    def __handle_class_modify_event(self, cpu, data, size):
        log.debug("__handle_class_modify_event 太好啦")
        log.info(f"handle_class_modify_event ->  event_id:{data.db_update_event_id}, "
                 f"modify_witch:{data.need_modify_class_id}, "
                 f"is_add:{data.is_add}, "
                 f"operand:{data.operand}, ")

        data = self.__bpf_obj["class_modify_event_sender"].event(data)
        rwclass_need_update: ReadWriteClass = self.get_all_policy()[1][data.need_modify_class_id]
        if rwclass_need_update is None:
            return
        if data.is_add == 1:
            rwclass_need_update.class_ids_can_read_this.add(data.operand)
        else:
            rwclass_need_update.class_ids_can_read_this.discard(data.operand)
        self.update_rwclass_id_to_rwclass(data.need_modify_class_id, rwclass_need_update)

    def __handle_class_new_event(self, cpu, data, size):
        log.debug("__handle_class_new_event 太好啦")
        data = ct.cast(data, ct.POINTER(ClassNewEventKernel)).contents

        # 将 二维数组 data.file_path 转为 python list

        file_path = []
        for i in range(GlobalVariableodule.MAX_FOLDER_DEPTH):
            # 将 类型为c_char_Array_255的data.file_path[i] 转为list
            file_path.append(bytearray(data.file_path[i]).decode().strip(b'\x00'.decode()))
        file_path = "/".join(list(filter(lambda i: len(i)!=0, file_path))[::-1])[1:]

        log.info(f"handle_class_new_event ->  event_id:{data.db_update_event_id}, "
                 f"Creator_id:{data.Creator_class_id}, "
                 f"file_path:{file_path}, "
                 f"new_id:{data.new_class_id}, "
                 )

        self.update_entity_path_to_rwclass_id(file_path, data.new_class_id)
        new_class: ReadWriteClass = copy.deepcopy(self.get_all_policy()[1][data.Creator_class_id])
        new_class.class_id = data.new_class_id
        new_class.owner_class_id = data.Creator_class_id
        new_class.class_ids_can_write_this.add(data.Creator_class_id)
        self.update_rwclass_id_to_rwclass(data.new_class_id, self.get_all_policy()[1][data.Creator_class_id])

    def __handle_class_delete_event(self, cpu, data, size):
        log.debug("__handle_class_delete_event 太好啦")

        data = ct.cast(data, ct.POINTER(ClassDeleteEventKernel)).contents



        # 将 二维数组 data.file_path 转为 python list
        file_path = []
        for i in range(GlobalVariableodule.MAX_FOLDER_DEPTH):
            # 将 类型为c_char_Array_255的data.file_path[i] 转为list
            file_path.append(bytearray(data.file_path[i]).decode().strip(b'\x00'.decode()))
        file_path = "/".join(list(filter(lambda i: len(i)!=0, file_path))[::-1])[1:]
        log.info(f"__handle_class_delete_event ->  event_id:{data.db_update_event_id}, "
                 f"file_path:{file_path}, "
                 )
        self.delete_entity_path_to_rwclass_id(file_path)

    def handle_all_form_ebpf(self):
        self.__bpf_obj.ring_buffer_poll(30)

